﻿using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace ParallelGrep.Utility
{
    /// <summary>
    /// アイコンヘルパー
    /// </summary>
	public sealed class ExtractIcon
	{
		[DllImport("Shell32.dll")]
		private static extern IntPtr SHGetFileInfo
			(
			string pszPath,
			uint dwFileAttributes,
			out ShFileInfo psfi,
			uint cbfileInfo,
			SHGFI uFlags
			);

		[DllImport("comctl32.dll")]
		private static extern int ImageList_GetImageCount(
			IntPtr himl
			);

		[DllImport("comctl32.dll")]
		private static extern IntPtr ImageList_GetIcon(
			IntPtr himl,
			int i,  
			uint flags 
			);

        #region GetIcon
        /// <summary>
        /// 指定したファイル名、アイコンサイズでアイコン情報を取得します。
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        /// <param name="isSmall">アイコンサイズ</param>
        /// <returns></returns>
		public static Icon GetIcon(string fileName, bool isSmall)
		{
			ShFileInfo info = new ShFileInfo(true);
			int cbFileInfo = Marshal.SizeOf(info);
			SHGFI flags;
            if (isSmall)
            {
                flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_LARGEICON;
            }
            else
            {
                flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_LARGEICON;
            }
			SHGetFileInfo(fileName, 256, out info,(uint)cbFileInfo, flags);
			return Icon.FromHandle(info.hIcon);
		}
        #endregion

        #region GetSelectedIcon
        /// <summary>
        /// 指定したファイル名、アイコンサイズでアイコン情報を取得します。
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        /// <param name="isSmall">アイコンサイズ</param>
        /// <returns></returns>
        public static Icon GetSelectedIcon(string fileName, bool isSmall)
		{
			ShFileInfo info = new ShFileInfo(true);
			int cbFileInfo = Marshal.SizeOf(info);
			SHGFI flags;
            if (isSmall)
            {
                flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_SMALLICON | SHGFI.SHGFI_OPENICON;
            }
            else
            {
                flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_LARGEICON | SHGFI.SHGFI_USEFILEATTRIBUTES | SHGFI.SHGFI_OPENICON;
            }
			try
			{
				SHGetFileInfo(fileName, 256, out info,(uint)cbFileInfo, flags);
				return Icon.FromHandle(info.hIcon);
			}
			catch
			{ // if the selected icon fails, try the standard icon
                if (isSmall)
                {
                    flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_SMALLICON;
                }
                else
                {
                    flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_LARGEICON | SHGFI.SHGFI_USEFILEATTRIBUTES;
                }
				SHGetFileInfo(fileName, 256, out info,(uint)cbFileInfo, flags);
				return Icon.FromHandle(info.hIcon);
			}
		}
        #endregion

        #region GetIconIndex
        /// <summary>
        /// 指定したファイル、イメージリストでイメージリストを出力します。
        /// </summary>
        /// <param name="fileName">ファイル名</param>
        /// <param name="imageList">イメージリスト</param>
        /// <returns>アイコン数</returns>
        public static int GetIconIndex(string fileName, ImageList imageList)
		{
			ShFileInfo info = new ShFileInfo(true);
			int cbFileInfo = Marshal.SizeOf(info);
			SHGFI flags;
			IntPtr hIcon;

			flags = SHGFI.SHGFI_SYSICONINDEX|SHGFI.SHGFI_SMALLICON;

            //IntPtr ret = SHGetFileInfo("C:\\", 256, out info, (uint)cbFileInfo, flags);
            IntPtr ret = SHGetFileInfo(fileName, 256, out info, (uint)cbFileInfo, flags);
			int nbIcon = ImageList_GetImageCount(ret);

			for (int i = 0; i < nbIcon; i++)
			{
				hIcon = ImageList_GetIcon(ret, i, 0);
				imageList.Images.Add (Icon.FromHandle(hIcon));
			}
			return info.iIcon;
        }
        #endregion
    }
}
